﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace SW.Winform.Commons
{
    public static class ImageHelper
    {
        #region 缩略图

        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <param name="sizeConfig">尺寸：" 100_100|200|200 "</param>
        /// <param name="isCoverFile">当缩略图存在时，是否覆盖文件, 默认是True</param>
        /// <param name="isUsmSharpen">是否进行锐化效果</param>
        public static void GenerateThumbImg(string filename, string sizeConfig, int quality)
        {
            if (string.IsNullOrEmpty(sizeConfig)) return;
            var arr = sizeConfig.Split('|').ToList();
            if (arr.Count == 0) return;
            arr.ForEach(a =>
            {
                var size = a.Split('_');
                int width = int.Parse(size[0]);
                int height = int.Parse(size[1]);
                GenerateThumbImg(filename, width, height, quality);
            });
        }

        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <param name="width">宽</param>
        /// <param name="height">高</param>
        /// <param name="isCoverFile">当缩略图存在时，是否覆盖文件, 默认是True</param>
        /// <param name="isUsmSharpen">是否进行锐化效果</param>
        public static void GenerateThumbImg(string filename, int width, int height, int quality)
        {
            // 原文件不存在,Return!
            if (!File.Exists(filename)) return;
            var newFileDir = Path.GetDirectoryName(filename) + "\\" + width + "_" + height + "\\";
            var newFileName = newFileDir + Path.GetFileName(filename);
            // 新文件目录不存在，创建!
            if (!Directory.Exists(newFileDir)) Directory.CreateDirectory(newFileDir);

            // 生成缩略图
            using (Image img = Image.FromFile(filename))
            {
                if (img.Width == width && img.Height == height) { File.Delete(newFileName); File.Copy(filename, newFileName); return; }
                if (width > 0 && height == 0)
                    height = (int)Math.Round(((float)width / img.Width) * img.Height, 0, MidpointRounding.AwayFromZero);
                if (width == 0 && height > 0)
                    width = (int)Math.Round(((float)height / img.Height) * img.Width, 0, MidpointRounding.AwayFromZero);
                if (width > 0 && height > 0)
                {
                    Bitmap hb = new System.Drawing.Bitmap(width, height);//创建图片对象
                    System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(hb);//创建画板并加载空白图像
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;//设置保真模式为高度保真
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                    g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                    Rectangle Rect = new Rectangle(0, 0, width, height);
                    g.DrawImage(img, Rect, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);//开始画图                   
                    SaveAsJPEG(hb, newFileName, quality);
                    g.Dispose();
                    hb.Dispose();
                }
            }
        }

        /// <summary>
        /// 保存JPG时用
        /// </summary>
        /// <param name="mimeType"></param>
        /// <returns>得到指定mimeType的ImageCodecInfo</returns>
        private static ImageCodecInfo GetCodecInfo(string mimeType)
        {
            ImageCodecInfo[] CodecInfo = ImageCodecInfo.GetImageEncoders();
            foreach (ImageCodecInfo ici in CodecInfo)
            {
                if (ici.MimeType == mimeType) return ici;
            }
            return null;
        }

        /// <summary>
        /// 保存为JPEG格式，支持压缩质量选项
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="FileName"></param>
        /// <param name="Qty"></param>
        /// <returns></returns>
        private static bool SaveAsJPEG(Bitmap bmp, string FileName, int Qty)
        {
            try
            {
                EncoderParameter p;
                EncoderParameters ps;
                ps = new EncoderParameters(1);
                p = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, Qty);
                ps.Param[0] = p;
                bmp.Save(FileName, GetCodecInfo("image/jpeg"), ps);
                return true;
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #region 图片水印

        /// <summary>
        /// 生成水印图片
        /// </summary>
        public static void GenerateWaterImg(string sourcefile, string waterfile, string targetfile, int quality, MarkPosition mp, int posX, int posY)
        {

            using (Image img = Image.FromFile(sourcefile))
            {
                var width = img.Width;
                var height = img.Height;
                Bitmap hb = new System.Drawing.Bitmap(width, height);//创建图片对象
                System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(hb);//创建画板并加载空白图像
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;//设置保真模式为高度保真
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                Rectangle Rect = new Rectangle(0, 0, width, height);
                g.DrawImage(img, Rect, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);//开始画图         
                AddWaterToImage(g, waterfile, mp, img.Width, img.Height, posX, posY);
                SaveAsJPEG(hb, targetfile, quality);
                g.Dispose();
                hb.Dispose();
            }
        }
     
        /// <summary>
        /// 添加水印到图片上
        /// </summary>
        /// <param name="picture"></param>
        /// <param name="waterMarkPath"></param>
        /// <param name="mp"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        private static void AddWaterToImage(Graphics picture, string waterfile, MarkPosition mp, int width, int height, int posX, int posY)
        {
            Image watermark = new Bitmap(waterfile);
            ImageAttributes imageAttributes = new ImageAttributes();
            ColorMap colorMap = new ColorMap();
            colorMap.OldColor = Color.FromArgb(255, 0, 255, 0);
            colorMap.NewColor = Color.FromArgb(0, 0, 0, 0);
            ColorMap[] remapTable = { colorMap };
            imageAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap);
            float[][] colorMatrixElements = {
                                                 new float[] {1.0f,  0.0f,  0.0f,  0.0f, 0.0f},
                                                 new float[] {0.0f,  1.0f,  0.0f,  0.0f, 0.0f},
                                                 new float[] {0.0f,  0.0f,  1.0f,  0.0f, 0.0f},
                                                 new float[] {0.0f,  0.0f,  0.0f,  0.3f, 0.0f},
                                                 new float[] {0.0f,  0.0f,  0.0f,  0.0f, 1.0f}
                                             };
            ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);
            int xpos = 0;
            int ypos = 0;
            int WatermarkWidth = 0;
            int WatermarkHeight = 0;
            double bl = 1d;
            if ((width > watermark.Width * 4) && (height > watermark.Height * 4))
            {
                bl = 1;
            }
            else if ((width > watermark.Width * 4) && (height < watermark.Height * 4))
            {
                bl = Convert.ToDouble(height / 4) / Convert.ToDouble(watermark.Height);

            }
            else
                if ((width < watermark.Width * 4) && (height > watermark.Height * 4))
                {
                    bl = Convert.ToDouble(width / 4) / Convert.ToDouble(watermark.Width);
                }
                else
                {
                    if ((width * watermark.Height) > (height * watermark.Width))
                    {
                        bl = Convert.ToDouble(height / 4) / Convert.ToDouble(watermark.Height);

                    }
                    else
                    {
                        bl = Convert.ToDouble(width / 4) / Convert.ToDouble(watermark.Width);

                    }
                }
            WatermarkWidth = watermark.Width; //Convert.ToInt32(watermark.Width * bl);
            WatermarkHeight = watermark.Height; //Convert.ToInt32(watermark.Height * bl);
            switch (mp)
            {
                case MarkPosition.Left_Top:
                    xpos = posX;
                    ypos = posY;
                    break;
                case MarkPosition.Right_Top:
                    xpos = width - WatermarkWidth - posX;
                    ypos = posY;
                    break;
                case MarkPosition.Right_Bottom:
                    xpos = width - WatermarkWidth - posX;
                    ypos = height - WatermarkHeight - posY;
                    break;
                case MarkPosition.Left_Bottom:
                    xpos = posX;
                    ypos = height - WatermarkHeight - posY;
                    break;
            }
            picture.DrawImage(watermark, new Rectangle(xpos, ypos, WatermarkWidth, WatermarkHeight), 0, 0, watermark.Width, watermark.Height, GraphicsUnit.Pixel, imageAttributes);
            watermark.Dispose();
            imageAttributes.Dispose();
        }

        /// <summary>
        /// 获取指定mimeType的ImageCodecInfo
        /// </summary>
        private static ImageCodecInfo GetImageCodecInfo(string mimeType)
        {
            ImageCodecInfo[] CodecInfo = ImageCodecInfo.GetImageEncoders();
            foreach (ImageCodecInfo ici in CodecInfo)
            {
                if (ici.MimeType == mimeType) return ici;
            }
            return null;
        }

        #endregion
    }

    /// <summary>
    /// 图片水印类型
    /// </summary>
    public enum MarkType
    {
        /// <summary>
        /// 不加水印
        /// </summary>
        None = 0,
        /// <summary>
        /// 文字水印
        /// </summary>
        Text = 1,
        /// <summary>
        /// 图片水印
        /// </summary>
        Picture = 2
    }

    /// <summary>
    /// 水印的位置
    /// </summary>
    public enum MarkPosition
    {
        /// <summary>
        /// 左上角
        /// </summary>
        Left_Top,

        /// <summary>
        /// 左下角
        /// </summary>
        Left_Bottom,

        /// <summary>
        /// 右上角
        /// </summary>
        Right_Top,

        /// <summary>
        /// 右下角
        /// </summary>
        Right_Bottom
    }
}
